<?php
/**
 * User: 784855684@qq.com
 * Date: 30/12/2017
 * Time: 17:13
 */
declare(strict_types=1);


namespace AppBundle\Controller;

use AppBundle\Entity\Material;
use AppBundle\Repository\MaterialRepository;
use AppBundle\Throwable\MaterialInUseException;
use AppBundle\Utils\Chars;
use AppBundle\Utils\MaterialUtil;
use Doctrine\ORM\OptimisticLockException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class MaterialController extends DefaultController
{

    /**
     * @Route("/material/overview")
     * @return Response
     */
    public function overviewAction()
    {
        return $this->render('material/overview.html.twig');
    }

    /**
     * @Route("/material/list")
     * @return Response
     */
    public function listAction()
    {
        /** @var MaterialRepository $respo */
        $respo = $this->getEntityManager()->getRepository(Material::class);
        /** @var Material[] $objects */
        $objects = $respo->findAllAvailable();
        $list = [];
        foreach ($objects as $object) {
            $list[] = $this->fetchInfo($object);
        }
        return $this->responseSuccess('', $list);
    }

    /**
     * @Route("/material/map")
     * @return JsonResponse
     */
    public function mapAction()
    {
        /** @var MaterialRepository $respo */
        $respo = $this->getEntityManager()->getRepository(Material::class);
        /** @var Material[] $objects */
        $objects = $respo->findAllAvailable();

        $list = [];
        foreach ($objects as $object) {
            $list[$object->getId()] = [
                'name' => $object->getName(),
            ];
        }
        return $this->responseSuccess('', $list);
    }

    /**
     * fetch infomation from material entity
     * @param Material $object
     * @param bool $full
     * @return array
     */
    private function fetchInfo(Material $object, bool $full = false)
    {
        $desc = $object->getDescription();
        if (!$full and mb_strlen($desc) > 20) {
            $desc = mb_substr($desc, 0, 20) . '...';
        }
        return [
            'id' => $object->getId(),
            'name' => $object->getName(),
            'description' => $desc,
            'price' => $object->getPrice(),
            'inventory' => $object->getInventory(),
            'unique_code' => $object->getUniqueCode(),
        ];
    }

    /**
     * @Route("/material/creation")
     * @param Request $request
     * @return JsonResponse
     */
    public function creationAction(Request $request)
    {
        # TODO:to validate

        $name = $request->request->get('name');
        $description = $request->request->get('description');
        $inventory = (int)$request->request->get('inventory');
        $price = (float)$request->request->get('price');

        $material = (new MaterialUtil($this->getDoctrine()->getManager()))->create($name, $description, $price, $inventory);

        return $this->responseSuccess('Material created!', $this->fetchInfo($material));
    }

    /**
     * @Route("/material/info")
     * @param Request $request
     * @return JsonResponse
     */
    public function infoAction(Request $request)
    {
        $id = (int)$request->request->get('id');
        $em = $this->getDoctrine()->getManager();
        /** @var Material $material */
        $material = $em->getRepository(Material::class)->find($id);
        if ($material) {
            return $this->responseSuccess('', $this->fetchInfo($material, true));
        } else {
            return $this->responseError(2001, "No Material found for id {$id}");
        }
    }

    /**
     * @Route("/material/edit")
     * @param Request $request
     * @return JsonResponse
     */
    public function editAction(Request $request)
    {
        $id = (int)$request->request->get('id');
        $em = $this->getDoctrine()->getManager();
        /** @var Material $material */
        $material = $em->getRepository(Material::class)->find($id);
        if (!$material) {
            return $this->responseError(2001, 'No Material found for id ' . $id);
        }
        $material->setPrice((float)$request->request->get('price'));
        $material->setName($request->request->get('name'));
        $material->setDescription($request->request->get('description'));
        $material->setInventory($request->request->get('inventory'));

        $em->flush();
        return $this->responseSuccess('Material updated', $this->fetchInfo($material));
    }

    /**
     * @Route("/material/remove")
     * @param Request $request
     * @return JsonResponse
     */
    public function removeAction(Request $request)
    {
        $id = (int)$request->request->get('id');
        $em = $this->getDoctrine()->getManager();
        /** @var Material $material */
        $material = $em->getRepository(Material::class)->find($id);
        try {
            (new MaterialUtil($em))->remove($material);
            return $this->responseSuccess('Remove success');
        } catch (MaterialInUseException $e) {
            return $this->responseError($e->getCode(), $e->getMessage());
        }
    }
}